package ldh.maker.handle;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import ldh.maker.constants.TreeNodeTypeEnum;
import ldh.maker.controller.MainController;
import ldh.maker.db.*;
import ldh.maker.util.FileUtil;
import ldh.maker.util.UiUtil;
import ldh.maker.vo.TreeNode;

import java.io.*;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by ldh on 2017/2/19.
 */
public class TreeContextMenuHandle {

    private ContextMenu treeContextMenu;
    private TreeView<TreeNode> projectTree;
    private MainController mainController;

    public TreeContextMenuHandle(ContextMenu treeContextMenu, TreeView<TreeNode> projectTree,
            MainController mainController) {
        this.projectTree = projectTree;
        this.treeContextMenu = treeContextMenu;
        this.mainController = mainController;

        initEventHandle();
    }

    private void initEventHandle() {
        initTreeContextMenu();

        treeContextMenu.setOnShowing(e->{
            TreeItem<TreeNode> treeItem = (TreeItem) projectTree.getSelectionModel().getSelectedItem();
            if (treeItem == null)  return;
            TreeNode treeData = treeItem.getValue();
            if (treeData.getType() == TreeNodeTypeEnum.PROJECT) {
                MenuItem openProject = new MenuItem("打开构建计划");
                MenuItem closeProject = new MenuItem("关闭构建计划");
                MenuItem deleteProject = new MenuItem("删除构建计划");
                deleteProject.setOnAction(e1->deleteProjectHandle());
                treeContextMenu.getItems().addAll(openProject, closeProject, deleteProject);
            } else if (treeData.getType() == TreeNodeTypeEnum.DATABASE) {
                treeContextMenu.getItems().clear();
                MenuItem createDb = new MenuItem("创建数据库连接");
                DbHandle.newConnection(createDb);
                MenuItem openDb = new MenuItem("打开数据库连接");
                MenuItem closeDb = new MenuItem("关闭数据库连接");
                treeContextMenu.getItems().addAll(createDb, openDb, closeDb);
            } else if (treeData.getType() == TreeNodeTypeEnum.CODE) {
                treeContextMenu.getItems().clear();
                MenuItem  run = new MenuItem("运行");
                MenuItem refresh = new MenuItem("刷新");
                refresh.setOnAction(e2->{
                    codeRefresh();
                });
                run.setOnAction(e2->{
                    try {
                        packageCode();
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                });
                treeContextMenu.getItems().addAll(refresh);
            } else if (treeData.getType() == TreeNodeTypeEnum.ITEM) {
                treeContextMenu.getItems().clear();

                if (treeItem.getParent().getValue().getType() != TreeNodeTypeEnum.CODE) {
                    String file = treeData.getData().toString();
                    if (treeItem.getParent().getValue().getText().equals("target") &&
                            (file.endsWith(".jar") || file.endsWith(".war"))) {
                        MenuItem  run = new MenuItem("运行");
                        treeContextMenu.getItems().addAll(run);
                        run.setOnAction(e2->{
                            try {
                                runProject(treeItem.getParent().getValue().getData().toString(), treeData.getText());
                            } catch (Exception e1) {
                                e1.printStackTrace();
                            }
                        });
                    }
                    return;
                }
                MenuItem  packageMvn = new MenuItem("打包并运行");
                packageMvn.setOnAction(e2->{
                    try {
                        packageCode();
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                });
                treeContextMenu.getItems().addAll(packageMvn);
            }
        });

        treeContextMenu.setOnHidden(e->{treeContextMenuClean();});
    }

    private void packageCode() throws Exception {
        TreeItem<TreeNode> treeItem = UiUtil.getCurrentTreeItem();
        String path = FileUtil.getSourceRoot();
        String codeRoot= path + "code/" + treeItem.getParent().getParent().getValue().getText() + "/" + treeItem.getValue().getText();
        Task<Void> task = new Task<Void>() {
            @Override protected Void call() throws Exception {
                updateMessage("开始编译代码");
                try {
//                    Process process = Runtime.getRuntime().exec("mvn clean package", new String[]{}, new File(codeRoot));
                    String cmd = "cmd /k cd " + codeRoot + " && mvn clean package -Pdev";
                    System.out.println("mvn command:" + cmd);
                    Process process = Runtime.getRuntime().exec(cmd);
                    int i = 1000;
                    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//                    BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                    String file = codeRoot + "/target/" + treeItem.getValue().getText() + "-1.0.war";
                    while(process.isAlive()) {
                        Thread.sleep(500);
                        String line = reader.readLine();
                        if (line == null || line.contains("Finished") || line.contains("BUILD SUCCESS")) {
                            System.out.println("end!!!!!!!!!!!!!!!!!!!!!!!");
                            process.destroy();
                            break;
                        } else if (line != null && line.contains("error")) {
                            System.out.println("error!!!!!!!!!!!!!!!!!!!!!!!");
                            process.destroy();
                            break;
                        } else {
                            System.out.println("line:" + line);
                            updateMessage(reader.readLine());
//                        updateMessage(error.readLine());
                            updateProgress(i, 300000);
                            i+=500;
                        }
                    }
                    updateProgress(300000, 300000);
                    done();
                    reader.close();
                } catch(Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        };

        UiUtil.STATUSBAR.textProperty().bind(task.messageProperty());
        UiUtil.STATUSBAR.progressProperty().bind(task.progressProperty());

        task.setOnSucceeded(event -> {
            UiUtil.STATUSBAR.textProperty().unbind();
            UiUtil.STATUSBAR.progressProperty().unbind();

            runCode();
        });

        new Thread(task).start();
    }

    private void runCode() {
        TreeItem<TreeNode> treeItem = UiUtil.getCurrentTreeItem();
        String path = FileUtil.getSourceRoot();
        String codeRoot= path + "code/" + treeItem.getParent().getParent().getValue().getText() + "/" + treeItem.getValue().getText() + "/target";
        String file = treeItem.getValue().getText() + "-1.0.war";
        File targetFile = new File(file);
        if (!targetFile.exists()) {
            file = treeItem.getValue().getText() + "-1.0.jar";
        }
        runProject(codeRoot, file);
    }

    private void runProject(String dir, String file) {
        String cmd = "cmd /c start java -jar " + dir + "//" + file + " --spring.profiles.active=dev";
        Task<Void> task = new Task<Void>() {
            @Override protected Void call() throws Exception {
                updateMessage("开始运行代码");
                Process process = Runtime.getRuntime().exec(cmd);
                process.waitFor();
                Thread.sleep(1000);
                updateProgress(300000, 300000);
                done();
                return null;
            }
        };

        UiUtil.STATUSBAR.textProperty().bind(task.messageProperty());
        UiUtil.STATUSBAR.progressProperty().bind(task.progressProperty());

        task.setOnSucceeded(event -> {
            UiUtil.STATUSBAR.textProperty().unbind();
            UiUtil.STATUSBAR.progressProperty().unbind();
        });

        new Thread(task).start();
    }

    private void codeRefresh() {
        TreeItem<TreeNode> treeItem = UiUtil.getCurrentTreeItem();
        String path = FileUtil.getSourceRoot();
        String codeJava = path + "/code/" + treeItem.getParent().getValue().getText();
//        String codeJava = path + "/code/" + treeItem.getParent().getValue().getText() + "/src/main/java";
//        String resourceJava = path + "/code/" + treeItem.getParent().getValue().getText() + "/src/main/resources";
//        String resources = path + "/code/" + treeItem.getValue().getText() + "/src/main/webapp";
        treeItem.getChildren().clear();
        Platform.runLater(()->{
            FileUtil.loadFileTree(codeJava, treeItem, true);
//            FileUtil.loadFileTree(resourceJava, treeItem);
//            FileUtil.loadFileTree(resources, treeItem);
        });
    }

    private void deleteProjectHandle() {
        TreeItem<TreeNode> treeItem = (TreeItem) projectTree.getSelectionModel().getSelectedItem();
        if (treeItem == null)  return;
        projectTree.getRoot().getChildren().remove(treeItem);
        new Thread(()->{
            try {
                TreeNodeDb.deleteTreeNode(treeItem.getValue());
                deleteTreeNode(treeItem.getValue());
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }).run();
    }

    private void deleteTreeNode(TreeNode root) throws SQLException {
        List<TreeNode> treeNodeList = TreeNodeDb.loadTreeNode(root);
        for (TreeNode treeNode : treeNodeList) {
            DbConnectionDb.deleteTreeNode(treeNode);
            SettingDb.delete(treeNode);
            PojoDb.delete(treeNode);
            PojoFunctionDb.deleteData(treeNode.getId());
            EnumDb.delete(treeNode);
            TableViewDb.delete(treeNode);
            TableNoDb.delete(treeNode);
            deleteTreeNode(treeNode);
            TreeNodeDb.deleteTreeNode(treeNode);
        }
    }

    private void treeContextMenuClean() {
        treeContextMenu.getItems().clear();
        initTreeContextMenu();
    }

    private void initTreeContextMenu() {
        MenuItem createProject = new MenuItem("创建构建计划");
        createProject.setOnAction(e->mainController.createProject());
        treeContextMenu.getItems().addAll(createProject);
    }

    private boolean isExisted(String file) {
        File f = new File(file);
        return f.exists();
    }

    private boolean isExisted() {
        TreeItem<TreeNode> treeItem = UiUtil.getCurrentTreeItem();
        String path = FileUtil.getSourceRoot();
        String file= path + "code/" + treeItem.getParent().getParent().getValue().getText() + "/" + treeItem.getValue().getText() + "/target/" + treeItem.getValue().getText() + "-1.0.war";
        return isExisted(file);
    }
}
